﻿using Roton.Memory;
using Roton.ZZT;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Roton.Wrapper
{
    /// <summary>
    /// Adapts IBoard to a Segment object.
    /// </summary>
    class BoardWrapper : IBoard
    {
        protected BoardWrapperProperties properties;
        protected Segment segment;

        public BoardWrapper(int offset, Segment segment, BoardWrapperProperties properties)
        {
            this.segment = segment;
            properties.OffsetCamera += offset;
            properties.OffsetDark += offset;
            properties.OffsetEnter += offset;
            properties.OffsetExits += offset;
            properties.OffsetMaxShots += offset;
            properties.OffsetName += offset;
            properties.OffsetRestartZap += offset;
            properties.OffsetTiles += offset;
            properties.OffsetTimeLimit += offset;
            this.properties = properties;
        }

        public int CameraX
        {
            get
            {
                return segment.Read16(properties.OffsetCamera);
            }
            set
            {
                segment.Write16(properties.OffsetCamera, value);
            }
        }

        public int CameraY
        {
            get
            {
                return segment.Read16(properties.OffsetCamera + 2);
            }
            set
            {
                segment.Write16(properties.OffsetCamera + 2, value);
            }
        }

        public bool Dark
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetDark);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetDark, value);
            }
        }

        public int EnterX
        {
            get
            {
                return segment.Read8(properties.OffsetEnter);
            }
            set
            {
                segment.Write8(properties.OffsetEnter, value);
            }
        }

        public int EnterY
        {
            get
            {
                return segment.Read8(properties.OffsetEnter + 1);
            }
            set
            {
                segment.Write8(properties.OffsetEnter + 1, value);
            }
        }

        public int ExitEast
        {
            get
            {
                return segment.Read8(properties.OffsetExits + 3);
            }
            set
            {
                segment.Write8(properties.OffsetExits + 3, value);
            }
        }

        public int ExitNorth
        {
            get
            {
                return segment.Read8(properties.OffsetExits);
            }
            set
            {
                segment.Write8(properties.OffsetExits, value);
            }
        }

        public int ExitSouth
        {
            get
            {
                return segment.Read8(properties.OffsetExits + 1);
            }
            set
            {
                segment.Write8(properties.OffsetExits + 1, value);
            }
        }

        public int ExitWest
        {
            get
            {
                return segment.Read8(properties.OffsetExits + 2);
            }
            set
            {
                segment.Write8(properties.OffsetExits + 2, value);
            }
        }

        public int Height
        {
            get
            {
                return properties.Height;
            }
        }

        public IString Name
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetName, segment);
            }
        }

        public int Shots
        {
            get
            {
                return segment.Read8(properties.OffsetMaxShots);
            }
            set
            {
                segment.Write8(properties.OffsetMaxShots, value);
            }
        }

        public int TimeLimit
        {
            get
            {
                return segment.Read16(properties.OffsetTimeLimit);
            }
            set
            {
                segment.Write16(properties.OffsetTimeLimit, value);
            }
        }

        public int Width
        {
            get
            {
                return properties.Width;
            }
        }

        public int GetTileColor(int x, int y)
        {
            return segment.Read8(properties.OffsetTiles + TileIndex(x, y) + 1);
        }

        public int GetTileID(int x, int y)
        {
            return segment.Read8(properties.OffsetTiles + TileIndex(x, y));
        }

        public void SetTileColor(int x, int y, int c)
        {
            segment.Write8(properties.OffsetTiles + TileIndex(x, y) + 1, c);
        }

        public void SetTileID(int x, int y, int id)
        {
            segment.Write8(properties.OffsetTiles + TileIndex(x, y), id);
        }

        private int TileIndex(int x, int y)
        {
            return (y + (x * properties.Height)) << 1;
        }
    }

    struct BoardWrapperProperties
    {
        public int Height;
        public int Width;
        public int OffsetName;
        public int OffsetTiles;
        public int OffsetMaxShots;
        public int OffsetDark;
        public int OffsetExits;
        public int OffsetRestartZap;
        public int OffsetEnter;
        public int OffsetCamera;
        public int OffsetTimeLimit;
    }
}
